package com.mlnx.push.websocket.client;

import com.alibaba.fastjson.JSON;
import com.mlnx.common.utils.MyLog;
import com.mlnx.mptp.ResponseCode;
import com.mlnx.mptp.push.PushPacket;
import com.mlnx.mptp.push.body.PushDataType;
import com.mlnx.push.websocket.client.utils.WebSocketListenner;
import com.mlnx.push.websocket.client.utils.WebSocketUtils;
import com.mlnx.tp.base.model.DeviceType;

import java.net.URI;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by amanda.shan on 2017/9/19.
 * websocket  通讯接口
 */
public class PushClient implements WebSocketListenner {

    private MyLog log = MyLog.getLog(getClass());

    private WebSocketUtils webSocketUtils;
    private boolean isRegister;

    private String name;
    private String password;
    private long timeoutMillis;

    protected final Map<Integer, ResponseFuture> responseMap =
            new ConcurrentHashMap<Integer, ResponseFuture>(1000);


    public PushClient(String name, String password, String serverIp, int port, long timeoutMillis) {
        this.name = name;
        this.password = password;
        this.timeoutMillis = timeoutMillis;

        URI uri = URI.create(String.format("ws://%s:%d/", serverIp, port));
        webSocketUtils = new WebSocketUtils(uri, this);
    }

    public boolean register() {

        PushPacket pushPacket = new PushPacket();
        pushPacket.register(name, password, DeviceType.USR);
        pushPacket.getBody().setKeepAliveTimer(2 * 60);

        if (send(pushPacket)) {
            isRegister = true;
            log.info("注册成功");
            return true;
        } else {
            log.info("注册失败");
            return false;
        }
    }

    public void ping() {
        PushPacket pushPacket = new PushPacket();
        pushPacket.ping(DeviceType.USR);

        String msg = JSON.toJSONString(pushPacket);
        try {
            webSocketUtils.sendString(msg);
        } catch (InterruptedException e) {
            log.error(e, "发送websocket数据");
        }
    }

    public boolean push(PushPacket pushPacket) {
        if (!isRegister) {
            if (!register()) {
                return false;
            }
        }
        return send(pushPacket);
    }


    private boolean send(PushPacket pushPacket) {
        try {

            Integer messageId = pushPacket.getBody().getMessageId();

            ResponseFuture<Boolean> responseFuture = new ResponseFuture(messageId);
            responseMap.put(messageId, responseFuture);

            String msg = JSON.toJSONString(pushPacket);
            webSocketUtils.sendString(msg);

            Boolean sucess = responseFuture.waitResponse(3000);

            return sucess == null ? false : sucess;
        } catch (Exception e) {
            log.error(e, "发送websocket数据");
        }
        return false;
    }

    @Override
    public void onMessage(String message) {
        log.debug("收到消息：" + message);

        PushPacket pushPacket = JSON.parseObject(message, com.mlnx.mptp.push.PushPacket.class);
        Map<PushDataType, Object> map = pushPacket.getBody().getPushDataMap();

        ResponseFuture<Boolean> responseFuture = responseMap.get(pushPacket.getBody().getMessageId());

        ResponseCode responseCode = pushPacket.getBody().getResponseCode();

        switch (pushPacket.getHeader().getPacketType()) {
            case Reg_ACK:
                if (!responseCode.equals(ResponseCode.SUCESS)) {
                    log.info("注册失败:" + responseCode);
                }
                break;
            case PUBLISH_ACK:
                if (!responseCode.equals(ResponseCode.SUCESS)) {
                    log.info("推送失败:" + responseCode);
                }
                break;
            default:
        }

        if (responseFuture != null) {
            if (responseCode.equals(ResponseCode.SUCESS)) {
                responseFuture.putResponse(true);
            } else {
                responseFuture.putResponse(false);
            }
        }

    }

    @Override
    public void onMessage(byte[] bs) {

    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        log.error(String.format("wesocket onClose:code = %d  reason=%s", code, reason));
        isRegister = false;
    }

    public void disConnect() {
        webSocketUtils.disConnect();
    }

}
